package com.yf.mediaserver.gb.sip;

import java.util.Map;
import java.util.TooManyListenersException;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;
import javax.sip.InvalidArgumentException;
import javax.sip.ListeningPoint;
import javax.sip.ObjectInUseException;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
import javax.sip.TransportNotSupportedException;


import com.yf.mediaserver.gb.config.SipConfig;
import com.yf.mediaserver.gb.sip.conf.DefaultProperties;
import com.yf.mediaserver.gb.sip.processors.SIPProcessorObserver;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

@Slf4j
@Component
public class SipLayer implements CommandLineRunner {


	//记录tpc连接
	private final  static Map<String, SipProviderImpl> TCP_SIP_PROVIDER_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();

	//记录udp连接
	private final static Map<String, SipProviderImpl> UDP_SIP_PROVIDER_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();

	@Resource
	private SipConfig sipConfig;

	/**
	 * SIP处理器
	 */
	@Resource
	private  SIPProcessorObserver sipProcessorObserver;

	private  static  final boolean IS_LOG = true;



	@Override
	public void run(String... args) throws Exception {
		addListeningPoint(sipConfig.getIp(),sipConfig.getPort());
	}


	private    void addListeningPoint(String monitorIp, int port){
		SipStackImpl sipStack;
		try {
			sipStack = (SipStackImpl) SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp, IS_LOG));
		} catch (PeerUnavailableException e) {
			log.error("[Sip Server] SIP服务启动失败， 监听地址{}失败,请检查ip是否正确", monitorIp);
			return;
		}

		try {
			//创建TCP
			ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP");
			SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);

			tcpSipProvider.setDialogErrorsAutomaticallyHandled();
			tcpSipProvider.addSipListener(sipProcessorObserver);
			TCP_SIP_PROVIDER_CONCURRENT_HASH_MAP.put(monitorIp, tcpSipProvider);

			log.info("[Sip Server] tcp://{}:{} 启动成功", monitorIp, port);
		} catch (TransportNotSupportedException
				 | TooManyListenersException
				 | ObjectInUseException
				 | InvalidArgumentException e) {
			log.error("[Sip Server] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确", monitorIp, port);
		}

		try {
			//创建UDP
			ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP");
			SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
			udpSipProvider.addSipListener(sipProcessorObserver);

			UDP_SIP_PROVIDER_CONCURRENT_HASH_MAP.put(monitorIp, udpSipProvider);

			log.info("[Sip Server] udp://{}:{} 启动成功", monitorIp, port);
		} catch (TransportNotSupportedException
				 | TooManyListenersException
				 | ObjectInUseException
				 | InvalidArgumentException e) {
			log.error("[Sip Server] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确" , monitorIp, port);
		}
	}

	/**
	 * 得到 UdpSipProvider
	 */
	public    SipProviderImpl getUdpSipProvider(String ip) {
		if (ObjectUtils.isEmpty(ip)) {
			return null;
		}
		return UDP_SIP_PROVIDER_CONCURRENT_HASH_MAP.get(ip);
	}

	/**
	 * 得到 UdpSipProvider 默认拿  udpSipProviderMap第一个
	 */
	public  SipProviderImpl getUdpSipProvider() {
		if (UDP_SIP_PROVIDER_CONCURRENT_HASH_MAP.size() != 1) {
			return null;
		}
		return UDP_SIP_PROVIDER_CONCURRENT_HASH_MAP.values().stream().findFirst().get();
	}

	/**
	 * 得到 TcpSipProvider 默认拿  TcpSipProviderMap第一个
	 */
	public  SipProviderImpl getTcpSipProvider() {
		if (TCP_SIP_PROVIDER_CONCURRENT_HASH_MAP.size() != 1) {
			return null;
		}
		return TCP_SIP_PROVIDER_CONCURRENT_HASH_MAP.values().stream().findFirst().get();
	}
	/**
	 * 得到 TcpSipProvider
	 */
	public  SipProviderImpl getTcpSipProvider(String ip) {
		if (ObjectUtils.isEmpty(ip)) {
			return null;
		}
		return TCP_SIP_PROVIDER_CONCURRENT_HASH_MAP.get(ip);
	}

	public  String getLocalIp(String deviceLocalIp) {
		if (!ObjectUtils.isEmpty(deviceLocalIp)) {
			return deviceLocalIp;
		}
		return getUdpSipProvider().getListeningPoint().getIPAddress();
	}


}
